#pragma once

#include <iostream>
#include <vector>
#include "InetAddr.hpp"
#include "log.hpp"
#include "mutex.hpp"

using namespace MyLog;
using namespace MutexModule;
class route
{
private:
    bool isexist(InetAddr &cli)
    {
        for(auto &client : _online_clients){
            if(client == cli){
                return true;
            }
        }
        return false;
    }
    void addclient(InetAddr &cli) { _online_clients.emplace_back(cli); }
    void deleteclient(InetAddr &cli)
    {
        for(auto iter = _online_clients.begin(); iter != _online_clients.end(); iter++){
            if(*iter == cli){
                _online_clients.erase(iter);
                break;
            }
        }
    }
public:
    route(){}
    ~route(){}
    void messag_routing(int sockfd, const std::string &message, InetAddr &client)
    {
        // 消息路由不是线程安全的，有的线程可能已经进入路由过程，而有的线程正在新增用户
        // 本质是因为该函数内部访问了公共的在线用户列表_online_clients
        // 未来，我们可以自定义协议，发送的消息规定一个结构体，里面有特殊的字段，用来区分该消息是什么类型的
        // 比如：登录消息，常规消息，退出消息
        // 我们也可以将新增用户，路由消息，删除用户，分离开，根据消息的不同，执行不同的操作
        // 并且还得保证每一个操作的安全
        // 这里我们简单的给路由消息加锁，来实现线程安全
        mutexguard lock(_mutex); 


        // 1.判断发送该消息的客户端是否已经在线
        if(!isexist(client)){
            LOG(loglevel::INFO) << "新增一个用户->" << "[" << client.InetToString() << "]";
            addclient(client);
        }

        // 2.将该客户端发送的消息，路由给其他在线的客户端，包括ta自己
        // 路由消息时，对消息进行描述---谁发的(模拟头像和昵称)
        std::string route_message = "[" + client.InetToString() + "]# " + message;
        for(auto &user : _online_clients){
            ssize_t n = sendto(sockfd
                , route_message.c_str()
                , sizeof(route_message)
                , 0
                , (struct sockaddr*)&(user.Getsockaddr()), sizeof(user.Getsockaddr()));
        }

        // 3.约定：如果用户发送了quit，表明客户退出
        if(message == "quit"){
            LOG(loglevel::INFO) << "删除一个用户->" << "[" << client.InetToString() << "]";
            deleteclient(client);
        }
    }
private:
    std::vector<InetAddr> _online_clients;
    Mutex _mutex;
};